﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

using Clipboard = System.Windows.Clipboard;
using DataFormats = System.Windows.DataFormats;
using DataObject = System.Windows.DataObject;
using MessageBox = System.Windows.MessageBox;

namespace MyEditor
{
    public class MultiSelectTreeViewHelper
    {
        private readonly TreeView tree;
        private readonly List<TreeViewItem> selectedItems = new();
        private TreeViewItem anchorItem;

        public IReadOnlyList<string> SelectedFiles => selectedItems.Select(i => i.Tag as string).Where(s => !string.IsNullOrEmpty(s)).ToList();

        public MultiSelectTreeViewHelper(TreeView tree)
        {
            this.tree = tree;
            tree.SelectedItemChanged += Tree_SelectedItemChanged;
        }

        private void Tree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (tree.SelectedItem is TreeViewItem item)
            {
                string path = item.Tag as string;
                if (string.IsNullOrEmpty(path)) return;

                bool ctrl = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
                bool shift = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);

                if (shift && anchorItem != null)
                {
                    SelectRange(anchorItem, item);
                }
                else if (ctrl)
                {
                    if (selectedItems.Contains(item)) DeselectItem(item);
                    else SelectItem(item);
                }
                else
                {
                    ClearAllSelections();
                    SelectItem(item);
                    anchorItem = item;
                }
            }
        }

        private void SelectItem(TreeViewItem item)
        {
            if (!selectedItems.Contains(item))
                selectedItems.Add(item);
            item.Background = Brushes.LightBlue;
        }

        private void DeselectItem(TreeViewItem item)
        {
            selectedItems.Remove(item);
            item.Background = Brushes.Transparent;
        }

        private void ClearAllSelections()
        {
            foreach (var i in new List<TreeViewItem>(selectedItems))
                DeselectItem(i);
        }

        private void SelectRange(TreeViewItem start, TreeViewItem end)
        {
            var allItems = GetAllVisibleTreeViewItems();
            int i1 = allItems.IndexOf(start);
            int i2 = allItems.IndexOf(end);
            if (i1 < 0 || i2 < 0) return;

            int from = Math.Min(i1, i2);
            int to = Math.Max(i1, i2);

            ClearAllSelections();
            for (int i = from; i <= to; i++)
                SelectItem(allItems[i]);
        }

        /// 获取所有可见的TreeView项
        /// <returns>返回包含所有可见TreeView项的列表</returns>
        private List<TreeViewItem> GetAllVisibleTreeViewItems()
        {
            // 创建一个新的列表来存储结果
            var result = new List<TreeViewItem>();
            // 遍历TreeView中的顶层项
            foreach (TreeViewItem item in tree.Items)
            {
                // 递归添加TreeView项及其子项
                AddTreeViewItemsRecursively(item, result);
            }

            // 返回包含所有可见TreeView项的列表
            return result;
        }

        /// 递归地将TreeViewItem及其展开的子项添加到结果列表中
        /// <param name="item">当前要处理的TreeViewItem</param>
        /// <param name="result">用于存储结果的TreeViewItem列表</param>
        private void AddTreeViewItemsRecursively(TreeViewItem item, List<TreeViewItem> result)
        {
            // 将当前项添加到结果列表中
            result.Add(item);
            // 检查当前项是否处于展开状态
            if (item.IsExpanded)
            {
                // 遍历当前项的所有子项
                foreach (TreeViewItem child in item.Items)
                {
                    // 递归调用处理每个子项
                    AddTreeViewItemsRecursively(child, result);
                }
            }
        }

        // 复制文件到剪贴板
        public void CopyFiles()
        {
            var files = SelectedFiles.Where(p => File.Exists(p) || Directory.Exists(p)).ToArray();
            if (files.Length == 0)
            {
                Toast.Show_success_Toast("没有选中的文件或目录");
                return;
            }

            Clipboard.SetDataObject(new DataObject(DataFormats.FileDrop, files), true);
            Toast.Show_success_Toast($"已复制 {files.Length} 个文件/目录到剪贴板");
        }

        // 复制文件名称到剪贴板
        public void CopyFileNames()
        {
            var names = SelectedFiles.Select(Path.GetFileName).Where(n => !string.IsNullOrEmpty(n)).ToArray();
            if (names.Length == 0)
            {
                Toast.Show_success_Toast("没有选中的文件或目录");
                return;
            }

            Clipboard.SetText(string.Join("\n", names));
            Toast.Show_success_Toast($"已复制 {names.Length} 个文件/目录名称");
        }
    }
}


